package com.credithc.eagleeye.spring.starter;
import com.credithc.eagleeye.agent.IEagleEyeAgent;
import com.credithc.eagleeye.agent.bean.EagleEyeAgentConfig;
import com.credithc.eagleeye.agent.factory.EagleEyeAgentFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
/**
 * 描 述: <br/>
 * 作 者: zhangjin<br/>
 * 创 建：2019年11月06日<br/>
 * 版 本：v1.0.0<br>
 * <p>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
public class EagleEyeAgentInitializer implements
        ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
    public static String getVersion() {
        Package pkg = EagleEyeAgentSpringApplicationRunListener.class.getPackage();
        return (pkg != null ? pkg.getImplementationVersion() : null);
    }

    private static final String[] EAGLE_EYE_BANNER = { "",
            " ______            _      ______           ",
            "|  ____|          | |    |  ____|          ",
            "| |__   __ _  __ _| | ___| |__  _   _  ___ ",
            "|  __| / _` |/ _` | |/ _ \\  __|| | | |/ _ \\",
            "| |___| (_| | (_| | |  __/ |___| |_| |  __/",
            "|______\\__,_|\\__, |_|\\___|______\\__, |\\___|" ,
            "              __/ |              __/ |     " ,
            "             |___/              |___/  "
    };

    //晚于EnvironmentDecryptApplicationInitializer
    private int order = Ordered.HIGHEST_PRECEDENCE + 16;

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        EagleEyeProperties eagleEyeProperties = initEagleEyeProperties(environment);
        if (eagleEyeProperties == null) {
            return;
        }
        for (String line : EAGLE_EYE_BANNER) {
            System.out.println(line);
        }
        System.out.println(String.format("EagleEye Version: %s\n", getVersion()));
        startEagleEye(eagleEyeProperties);

    }

    @Override
    public int getOrder() {
        return this.order;
    }

    protected static IEagleEyeAgent startEagleEye(EagleEyeProperties eagleEyeProperties) {
        IEagleEyeAgent eagleEyeAgent=null;
        if (StringUtils.isNotBlank(eagleEyeProperties.getConfig())) {
            eagleEyeAgent = EagleEyeAgentFactory.createInstance(eagleEyeProperties.getConfig());
        } else {
            EagleEyeAgentConfig eagleEyeAgentConfig = new EagleEyeAgentConfig();
            eagleEyeAgentConfig.setAgentClientName(eagleEyeProperties.getClientName());
            eagleEyeAgentConfig.setAgentEnv(eagleEyeProperties.getEnv());
            eagleEyeAgentConfig.setAgentMode(eagleEyeProperties.getMode());
            eagleEyeAgentConfig.setAgentPlatform(eagleEyeProperties.getPlatformName());
            if (eagleEyeProperties.getRedis() != null) {
                eagleEyeAgentConfig.setRedisAddress(eagleEyeProperties.getRedis().getAddress());
                eagleEyeAgentConfig.setRedisMaxTotal(eagleEyeProperties.getRedis().getMaxTotal());
                eagleEyeAgentConfig.setRedisMinIdle(eagleEyeProperties.getRedis().getMinIdle());
                eagleEyeAgentConfig.setRedisMaxIdle(eagleEyeProperties.getRedis().getMaxIdle());
                eagleEyeAgentConfig.setRedisMaxWaitMillis(eagleEyeProperties.getRedis().getMaxWaitMillis());
                eagleEyeAgentConfig.setRedisTimeout(eagleEyeProperties.getRedis().getTimeout());
            }
            if (eagleEyeProperties.getIce() != null) {
                eagleEyeAgentConfig.setIceLocator(eagleEyeProperties.getIce().getLocator());
                eagleEyeAgentConfig.setIceLocatorCacheTimeout(eagleEyeProperties.getIce().getLocatorCacheTimeout());
            }
            if (eagleEyeProperties.getHttp() != null) {
                eagleEyeAgentConfig.setHttpHost(eagleEyeProperties.getHttp().getHost());
                eagleEyeAgentConfig.setHttpPort(eagleEyeProperties.getHttp().getPort());
            }
            if (eagleEyeProperties.getPlugin() != null) {
                eagleEyeAgentConfig.setEnableMvcParameter(eagleEyeProperties.getPlugin().isEnableMvcParameter());
                eagleEyeAgentConfig.setEnableMybatisSql(eagleEyeProperties.getPlugin().isEnableMybatisSql());
                eagleEyeAgentConfig.setEnableMybatisResult(eagleEyeProperties.getPlugin().isEnableMybatisResult());
                if (eagleEyeProperties.getPlugin().getMybatisMaxSqlLength() > 0) {
                    eagleEyeAgentConfig.setMybatisMaxSqlLength(eagleEyeProperties.getPlugin().getMybatisMaxSqlLength());
                }
                eagleEyeAgentConfig.setEnableMybatisConvertSql(eagleEyeProperties.getPlugin().isEnableMybatisConvertSql());
                eagleEyeAgentConfig.setEnablePrintLog(eagleEyeProperties.getPlugin().isEnablePrintLog());
            }
            eagleEyeAgent=EagleEyeAgentFactory.createInstance(eagleEyeAgentConfig);
        }
        return eagleEyeAgent;
    }

    private EagleEyeProperties initEagleEyeProperties(ConfigurableEnvironment environment) {
        EagleEyeProperties eagleEyeProperties = new EagleEyeProperties();

        String config = environment.getProperty("spring.eagle.agent.config");
        String platformName = environment.getProperty("spring.eagle.agent.platformName");
        if(platformName==null) {
            platformName = environment.getProperty("spring.eagle.agent.platform-name");
        }
        if (StringUtils.isBlank(config) && StringUtils.isBlank(platformName)) {
            return null;
        }

        String clientName = environment.getProperty("spring.eagle.agent.clientName");
        if(clientName==null) {
            clientName = environment.getProperty("spring.eagle.agent.client-name");
        }
        String env = environment.getProperty("spring.eagle.agent.env");
        String mode = environment.getProperty("spring.eagle.agent.mode");

        eagleEyeProperties.setConfig(config);
        eagleEyeProperties.setPlatformName(platformName);
        eagleEyeProperties.setClientName(clientName);
        eagleEyeProperties.setEnv(env);
        eagleEyeProperties.setMode(mode);

        if (StringUtils.isNotBlank(mode)) {
            switch (mode) {
                case "http":
                    String httpHost = environment.getProperty("spring.eagle.agent.http.host");
                    String httpPort = environment.getProperty("spring.eagle.agent.http.port");
                    EagleEyeProperties.HttpConfig httpConfig = new EagleEyeProperties.HttpConfig();
                    httpConfig.setHost(httpHost);
                    httpConfig.setPort(httpPort);
                    eagleEyeProperties.setHttp(httpConfig);
                    break;
                case "redis":
                    String redisAddress = environment.getProperty("spring.eagle.agent.redis.address");
                    int redisMaxTotal = environment.getProperty("spring.eagle.agent.redis.maxTotal",Integer.class);
                    int redisMinIdle = environment.getProperty("spring.eagle.agent.redis.minIdle",Integer.class);
                    int redisMaxIdle = environment.getProperty("spring.eagle.agent.redis.maxIdle",Integer.class);
                    long redisMaxWaitMillis = environment.getProperty("spring.eagle.agent.redis.maxWaitMillis",Long.class);
                    int redisTimeout = environment.getProperty("spring.eagle.agent.redis.timeout",Integer.class);

                    EagleEyeProperties.RedisConfig redisConfig = new EagleEyeProperties.RedisConfig();
                    redisConfig.setAddress(redisAddress);
                    redisConfig.setMaxTotal(redisMaxTotal);
                    redisConfig.setMinIdle(redisMinIdle);
                    redisConfig.setMaxIdle(redisMaxIdle);
                    redisConfig.setMaxWaitMillis(redisMaxWaitMillis);
                    redisConfig.setTimeout(redisTimeout);
                    eagleEyeProperties.setRedis(redisConfig);
                    break;
                default:
                    break;
            }
        }

        EagleEyeProperties.PluginConfig pluginConfig = new EagleEyeProperties.PluginConfig();

        Boolean pluginEnableMvcParameter = environment.getProperty("spring.eagle.agent.plugin.enableMvcParameter",Boolean.class);
        if(pluginEnableMvcParameter==null) {
            pluginEnableMvcParameter = environment.getProperty("spring.eagle.agent.plugin.enable-mvc-parameter", Boolean.class, true);
        }

        Boolean pluginEnableMybatisSql = environment.getProperty("spring.eagle.agent.plugin.enableMybatisSql", Boolean.class);
        if(pluginEnableMybatisSql==null) {
            pluginEnableMybatisSql = environment.getProperty("spring.eagle.agent.plugin.enable-mybatis-sql", Boolean.class, true);
        }

        Boolean pluginEnableMybatisResult = environment.getProperty("spring.eagle.agent.plugin.enableMybatisResult", Boolean.class);
        if(pluginEnableMybatisResult==null) {
            pluginEnableMybatisResult = environment.getProperty("spring.eagle.agent.plugin.enable-mybatis-result", Boolean.class, true);
        }

        Integer pluginMybatisMaxSqlLength = environment.getProperty("spring.eagle.agent.plugin.mybatisMaxSqlLength", Integer.class);
        if(pluginMybatisMaxSqlLength==null) {
            pluginMybatisMaxSqlLength = environment.getProperty("spring.eagle.agent.plugin.mybatis-max-sql-length", Integer.class, 4000);
        }

        Boolean pluginEnableMybatisConvertSql = environment.getProperty("spring.eagle.agent.plugin.enableMybatisConvertSql", Boolean.class);
        if(pluginEnableMybatisConvertSql==null) {
            pluginEnableMybatisConvertSql = environment.getProperty("spring.eagle.agent.plugin.enable-mybatis-convert-sql", Boolean.class, true);
        }

        Boolean pluginEnablePrintLog = environment.getProperty("spring.eagle.agent.plugin.enablePrintLog", Boolean.class);
        if(pluginEnablePrintLog==null) {
            pluginEnablePrintLog = environment.getProperty("spring.eagle.agent.plugin.enable-print-log", Boolean.class, false);
        }

        pluginConfig.setEnableMvcParameter(pluginEnableMvcParameter);
        pluginConfig.setEnableMybatisSql(pluginEnableMybatisSql);
        pluginConfig.setEnableMybatisResult(pluginEnableMybatisResult);
        pluginConfig.setMybatisMaxSqlLength(pluginMybatisMaxSqlLength);
        pluginConfig.setEnableMybatisConvertSql(pluginEnableMybatisConvertSql);
        pluginConfig.setEnablePrintLog(pluginEnablePrintLog);

        eagleEyeProperties.setPlugin(pluginConfig);
        return eagleEyeProperties;
    }
}
